package primary.primary0;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * 设计一个对象cache, 他支持下列两个基本操作:
 * set(id, object), 根据id设置对象;
 * get(id): 根据id得到一个对象;
 * 同时它有下面几个性质:
 * 1: x秒自动过期, 如果cache内的对象, x秒内没有被get或者set过, 则会自动过期;
 * 2: 对象数限制, 该cache可以设置一个n, 表示cache最多能存储的对象数;
 * 3: LRU置换, 当进行set操作时, 如果此时cache内对象数已经到达了n个, 则cache自动将最久未被使用过的那个对象剔除, 腾出空间放置新对象;
 * 请你设计这样一个cache;
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        String[] split = "1.1.1".split("\\.");

        System.out.println(Arrays.toString(split));
    }

    static class LRU{

        int capacity;

        int expireSecods;

        Node head;
        Node tail;

        class Node{
            Node pre;
            Node next;

            String key;
            String value;
            Date accessDate;
        }

        Map<String, Node> record = new HashMap<>();

        public LRU(int _capacity, int _expireSecods){
            this.capacity = _capacity;
            this.expireSecods = _expireSecods;
            head = new Node();
            tail = new Node();
            head.next = tail;
            tail.pre = head;
        }

        public void set(String key, String value){
            if(record.containsKey(key)){
                // 存在 更新
                Node curNode = record.get(key);
                curNode.value = value;
                aferAccess(curNode);
            }else{
                // 新增
                if(record.size() == capacity){
//                    if(capacity == 0){
//                        return;
//                    }
                    // 删除最旧的
                    Node toRemove = tail.pre;
                    record.remove(toRemove.key);
                    afterRemove(toRemove);
                }

                Node toInsert = new Node();
                toInsert.key = key;
                toInsert.value = value;
                record.put(key, toInsert);
                afterInsert(toInsert);

            }
        }

        public String get(String key){
            if(record.containsKey(key)){
                Node curNode = record.get(key);
                if(new Date().getSeconds() > curNode.accessDate.getSeconds() + expireSecods){
                    record.remove(curNode.key);
                    afterRemove(curNode);
                    return null;
                }
                aferAccess(curNode);
                return curNode.value;
            }
            return null;
        }

        private void aferAccess(Node node){
            node.accessDate = new Date();
            afterRemove(node);
            afterInsert(node);

        }

        private void afterRemove(Node node){
            Node pre = node.pre;
            Node next = node.next;
            pre.next = next;
            next.pre = pre;
        }

        private void afterInsert(Node node){
            node.accessDate = new Date();
            Node next = head.next;
            head.next = node;
            node.pre = head;
            node.next = next;
            next.pre = node;
        }
    }

}
